package com.ymx.darling.dialect.keygenerator;

import com.ymx.darling.bean.entity.BeanInfo;
import com.ymx.darling.bean.entity.BeanInfoManager;
import com.ymx.darling.bean.entity.FieldInfo;
import com.ymx.darling.bean.entity.id.IdType;
import com.ymx.darling.bean.sql.Statement;
import com.ymx.darling.exception.ExceptionFactory;
import com.ymx.darling.executor.Executor;
import com.ymx.darling.util.ReflectUtil;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * @author 爱Java的小于
 */
public class OracleKeyGenerator implements KeyGenerator{
    @Override
    public void processBefore(List<Object> entityList, Statement statement) throws SQLException {
        // 获取被插入实体的类型
        Class<?> entityType = entityList.get(0).getClass();
        BeanInfo beanInfo = BeanInfoManager.getBeanInfo(entityType);
        FieldInfo idColumnInfo = beanInfo.getIdColumnInfo();
        String sequenceSql = this.getSequenceSql(idColumnInfo.getKeySequence(), statement.getInsertBatchSize());
        Statement sequenceStatement = this.newGenerateKeyStatement(statement, sequenceSql, idColumnInfo.getField().getType());
        // 执行sql获取序列值
        Executor executor = statement.getExecutor();
        List<Object> sequences = executor.queryList(sequenceStatement);
        // 设置序列值
        try {
            entityList.forEach(entity -> ReflectUtil.setValue(idColumnInfo.getField(), entity, sequences.get(0)));
        } catch (Exception exception) {
            throw ExceptionFactory.wrapException(String.format("为字段%s.%s设置序列值时抛出异常", beanInfo.getModule().getName(), idColumnInfo.getProperty()), exception);
        }
    }


    private String getSequenceSql(String incrementerName, int batchSize) {
        String sql = "SELECT " + incrementerName + ".NEXTVAL FROM DUAL";
        if (batchSize > 1) {
            sql += " connect by level <= " + batchSize;
        }
        return sql;
    }


    @Override
    public void processAfter(List<Object> entityList, Statement statement, PreparedStatement preparedStatement) throws SQLException {
    }


    @Override
    public IdType getIdType() {
        return IdType.SEQUENCE;
    }
}
